#include <memory>
#include "Thread.hpp"
#include "Mutex.hpp"
#include <unistd.h>

int tickets = 10000;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


void* start_routine(void* args)
{
    while(true)
    {
        {
            LockGaurd mtx(&mutex);//保护了临界区中的临界资源
            //但是对于锁能少用就少用，迫不得已，必须得用锁就尽量让其范围尽量的小，因为锁很容易产生问题，最后造成死锁的问题
            //死锁的四大特性：互斥，环路问题，请求与保持，不剥夺
            //防止死锁的方法就是破坏这其中的某一种特性，正常就让加锁的顺序相同，这可以解决环路问题
            //银行家算法，死锁检测算法
            if(tickets > 0)
            {
                std::string name = static_cast<const char*>(args);
                std::cout << name << " get tickets: " << tickets-- << std::endl; 
            }
            else 
            {
                break;
            }
        }
        usleep(1000);
        //由于代码转化为汇编语言最少是3条：将数据从内存读到 CPU，CPU 对数据进行处理，将数据写回内存
        //而我们的代码是并发执行的，当我们的汇编语言只执行第一步的时候，可能就进行了线程切换
        //然后该数据的上下文被保存，此时假如我们的 tickets 此时为 1，然后后面三个线程也是如此，此时等到又切换到回来的时候
        //然后再对 tickets 进行操作，此时，我们执行这个代码后，tickets 为 0，但是，别的线程还是直接执行之前的上下文
        //此时，就会导致明明 tickets 已经小于 0 了，但是仍然后往后执行代码
        //最终就导致了线程不安全的问题，此时，这个函数也被称为不可重入函数
    }
    return nullptr;
}

int main()
{
    std::unique_ptr<Thread> t1(new Thread(start_routine, (void*)"usr 1", 1));
    std::unique_ptr<Thread> t2(new Thread(start_routine, (void*)"usr 2", 2));
    std::unique_ptr<Thread> t3(new Thread(start_routine, (void*)"usr 3", 3));
    std::unique_ptr<Thread> t4(new Thread(start_routine, (void*)"usr 4", 4));
    t1->join();
    t2->join();
    t3->join();
    t4->join();
    
    return 0;
}



















// #include "Thread.hpp"
// #include <unistd.h>

// void* start_routine(void* args)
// {
//     std::string task = static_cast<const char*>(args);
//     while(true)    
//     {
//         std::cout << task << std::endl;
//         sleep(1);
//     }
//     return nullptr;
// }

// int main()
// {
//     Thread* td1 = new Thread(start_routine, (void*)"log", 1);
//     Thread* td2 = new Thread(start_routine, (void*)"save", 1);
//     td1->join();
//     td2->join();
//     return 0;
// }

// #include <iostream>
// #include <vector>
// #include <pthread.h>
// #include <unistd.h>
// #include <cstdio>
// #include <cassert>


// #define THREADS_NUM 5/*线程数量*/

// class threads/*线程信息*/
// {
// public:
//     char namebuffer[64];//线程名字
//     pthread_t tid;      //线程id
// };

// void *start_routine(void* arg)
// {
//     int cnt = 5;//5s后线程结束
//     //子线程进行的操作
//     // threads* th = static_cast<threads*>(arg);//强制类型转换
//     //while(true)
//     while(cnt)
//     {
//         // printf("cnt: %d 子进程: %s id: 0x%x\n", cnt--, th->namebuffer, th->tid);
//         std::cout << "hello thread" << std::endl;
//         sleep(1);
//     }
//     return (void*)110;
// }

// int main()
// {
//     // std::vector<threads*> tds;
//     // for(int i = 0; i < THREADS_NUM; i++)
//     // {
//     //     threads* ts = new threads;
//     //     snprintf(ts->namebuffer, sizeof(ts->namebuffer), "thread %d", i+1);
//     //     pthread_create(&ts->tid, nullptr, start_routine, ts);
//     //     tds.push_back(ts);
//     // }

//     pthread_t tid;
//     pthread_create(&tid, nullptr, start_routine, nullptr);
//     pthread_detach(tid);
//     int n = pthread_join(tid, nullptr);
//     std::cout << n << std::endl;
//     // for(int i = 0; i < THREADS_NUM/2; i++)
//     // {
//     //     pthread_cancel(tds[i]->tid);
//     // }

//     // for(auto it: tds)
//     // {
//     //     void *ret;
//     //     pthread_join(it->tid, &ret);
//     //     std::cout << "thread: " << it->namebuffer << " wait success , ret: " << (long long)ret << std::endl;
//     //     delete it;
//     // }//打印进程结束的信息

//     std::cout << "main thread quit success" << std::endl;

//     return 0;
// }